package com.cloud2eye.base.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/** 
 * 
 * 描述：execl导入导出
 * 
 * @author :zhqb
 * 
 * @date :2016年05月20日 上午9:35:52 
 * 
 */
public class POIUtil {
	
	public static HSSFWorkbook toWorkBook(String fileName,String[] titles,List<List> dataList){
		HSSFWorkbook workBook = new HSSFWorkbook();//创建工作薄
		HSSFSheet sheet = workBook.createSheet(fileName);//创建工作表
		sheet.addMergedRegion(new CellRangeAddress(0,(short)0,0,(short)5));
		sheet.setDefaultColumnWidth(20);
		
		int cellTitleIndex = 0;
		int rowDataIndex=2;
	
		HSSFRow  titleRow = sheet.createRow(0);//创建行
		titleRow.setHeight((short) 450);//设置行高
		
		HSSFCell  titleCell = titleRow.createCell(0);//创建一行对应的列数
		titleCell.setCellValue(fileName);//将文件名称set到第一行上的第一列中
		CellStyle style = workBook.createCellStyle();
		style = getTileStyle(workBook);
		titleCell.setCellStyle(style);//设置工作表表头的样式
		//设置表头
		HSSFRow  headerRow = sheet.createRow(1);
		
		for(String title:titles){
			HSSFCell cell = headerRow.createCell(cellTitleIndex);
			cell.setCellStyle(getHeaderStyle(workBook));
			cell.setCellValue(title);
			cellTitleIndex++;
		}
		
		for(List list:dataList){
			int cellDataIndex = 0;
			HSSFRow  row = sheet.createRow(rowDataIndex);
			for(Object object :list ){
				HSSFCell cell = row.createCell(cellDataIndex);
				cell.setCellValue(object!=null?object.toString():"0");
				cell.setCellStyle(style);
				cellDataIndex++;
			}
			rowDataIndex++;
		}
		return workBook;
	}
	/**
	 * 
	 * @param fileName
	 * @param titles Excel头标题
	 * @param columnConfig 头标题对应的属性值
	 * @param dataList 填充的数据
	 * @return
	 */
	public static HSSFWorkbook toWorkBook(String fileName,String[] titles,String[] columnConfig,JSONArray dataList){
		HSSFWorkbook workBook = new HSSFWorkbook();
		HSSFSheet sheet = workBook.createSheet(fileName);
		sheet.setDefaultColumnWidth(20);
		int cellTitleIndex = 0;
	
		int rowDataIndex=2;
		//设置表头
		HSSFRow  titleRow = sheet.createRow(0);
		titleRow.setHeight((short) 120);
		HSSFCell  titleCell = titleRow.createCell(0);
		titleCell.setCellValue(fileName);
		titleCell.setCellStyle(getTileStyle(workBook));
		
		HSSFRow  headerRow = sheet.createRow(1);
		for(String title:titles){
			HSSFCell cell = headerRow.createCell(cellTitleIndex);
			cell.setCellValue(title);
			cell.setCellStyle(getHeaderStyle(workBook));
			cellTitleIndex++;
		}
		for(Object list:dataList){
			JSONObject object = (JSONObject) list;
			int cellDataIndex = 0;
			HSSFRow  row = sheet.createRow(rowDataIndex);

			for(String column:columnConfig ){
				HSSFCell cell = row.createCell(cellDataIndex);
				cell.setCellValue(object.getString(column));
				cell.setCellStyle(getDefaultStyle(workBook));
				cellDataIndex++;
			}
			rowDataIndex++;
		}
		return workBook;
			
		
	}
	
	/**
	 * 合并值相同的列
	 * @param sheet
	 * @param cellIndex 合并的列索引
	 */
	public static void mergeCell(HSSFSheet sheet,int cellIndex){
		int rowLength = sheet.getLastRowNum();//行数
		Map<Short,Short> mergeRowIndexMap = new HashMap<Short,Short>();
		HSSFCellStyle style = sheet.getWorkbook().createCellStyle(); // 样式对象    
	    style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 垂直    
//	    style.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 水平 
		for(short rowIndex=1;rowIndex<rowLength;rowIndex++){
			  String cellValue = sheet.getRow(rowIndex).getCell(cellIndex).getStringCellValue();
			  for(short nextIndex=(short) (rowIndex+1);nextIndex<=rowLength;nextIndex++){
				  String nextCellValue = sheet.getRow(nextIndex).getCell(cellIndex).getStringCellValue();
				  if(cellValue.equals(nextCellValue)){
					  short tempIndex  = rowIndex;
					  mergeRowIndexMap.put(tempIndex, nextIndex);
					  if(nextIndex==rowLength){
						  rowIndex=nextIndex;
					  }
				  }else{
					  if(mergeRowIndexMap.containsKey(rowIndex)){
						  rowIndex=(short) (nextIndex-1);
					  }
					  break;
				  }
			  }
			} 
		  for(Short beginRow:mergeRowIndexMap.keySet()){
			  short endRow = mergeRowIndexMap.get(beginRow);
			  sheet.addMergedRegion(new CellRangeAddress(beginRow, endRow, cellIndex, cellIndex));
		      sheet.getRow(beginRow).getCell(cellIndex).setCellStyle(getDefaultStyle(sheet.getWorkbook())); // 样式  
		  }
		
		
	}
	
	private static HSSFCellStyle getDefaultStyle(HSSFWorkbook workBook){
		HSSFCellStyle cellStyle = workBook.createCellStyle();
		cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框    
		cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框    
		cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框    
		cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框    
		cellStyle.setWrapText(true);
		return cellStyle;
	}
	
	private static HSSFCellStyle getHeaderStyle(HSSFWorkbook workBook){
		HSSFCellStyle cellStyle = workBook.createCellStyle();
		cellStyle.cloneStyleFrom(getDefaultStyle(workBook));
		HSSFFont font = workBook.createFont();//设置字体大小
		font.setFontHeightInPoints((short) 12); // 字体高度
		font.setFontName("黑体"); // 字体
		cellStyle.setFont(font);
		return cellStyle;
	}
	
	private static HSSFCellStyle getTileStyle(HSSFWorkbook workBook){
		HSSFCellStyle cellStyle = workBook.createCellStyle();
		cellStyle.cloneStyleFrom(getDefaultStyle(workBook));
		HSSFFont font = workBook.createFont();
		font.setFontHeightInPoints((short) 14); // 字体高度
		font.setFontName("黑体"); // 字体
		cellStyle.setFont(font);
//		cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		return cellStyle;
	}
	 /**
     * 对外提供读取excel 的方法
     * */
    public static List<List<Object>> readExcel(File file) throws IOException {
        String fileName = file.getName();
        String extension = fileName.lastIndexOf(".") == -1 ? "" : fileName
                .substring(fileName.lastIndexOf(".") + 1);
        if ("xls".equals(extension)) {
            return read2003Excel(file);
        } else if ("xlsx".equals(extension)) {
            return read2007Excel(file);
        } else {
            throw new IOException("不支持的文件类型");
        }
    }
    /**
     * 读取 office 2003 excel
     * @throws IOException
     * @throws FileNotFoundException
     */
    private static List<List<Object>> read2003Excel(File file)
            throws IOException {
        List<List<Object>> list = new LinkedList<List<Object>>();
        HSSFWorkbook hwb = new HSSFWorkbook(new FileInputStream(file));
        HSSFSheet sheet = hwb.getSheetAt(0);
        Object value = null;
        HSSFRow row = null;
        HSSFCell cell = null;
        int counter = 0;
        for (int i = sheet.getFirstRowNum(); counter < sheet
                .getPhysicalNumberOfRows(); i++) {
            row = sheet.getRow(i);
            if (row == null) {
                continue;
            } else {
                counter++;
            }
            List<Object> linked = new LinkedList<Object>();
            for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
                cell = row.getCell(j);
                if (cell == null) {
                    continue;
                }
                DecimalFormat df = new DecimalFormat("#");// 格式化 number String 字符
                SimpleDateFormat sdf = new SimpleDateFormat(
                        "yyyy-MM-dd HH:mm:ss");// 格式化日期字符串
                DecimalFormat nf = new DecimalFormat("#");// 格式化数字
                switch (cell.getCellType()) {
                    case XSSFCell.CELL_TYPE_STRING:
                        System.out.println(i + "行" + j + " 列 is String type");
                        value = cell.getStringCellValue();
                        break;
                    case XSSFCell.CELL_TYPE_NUMERIC:
                        System.out.println(i + "行" + j
                                + " 列 is Number type ; DateFormt:"
                                + cell.getCellStyle().getDataFormatString());
                        if ("@".equals(cell.getCellStyle().getDataFormatString())) {
                            value = df.format(cell.getNumericCellValue());
                        } else if ("General".equals(cell.getCellStyle()
                                .getDataFormatString())) {
                            value = nf.format(cell.getNumericCellValue());
                        } else {
                            value = sdf.format(HSSFDateUtil.getJavaDate(cell
                                    .getNumericCellValue()));
                        }
                        break;
                    case XSSFCell.CELL_TYPE_BOOLEAN:
                        System.out.println(i + "行" + j + " 列 is Boolean type");
                        value = cell.getBooleanCellValue();
                        break;
                    case XSSFCell.CELL_TYPE_BLANK:
                        System.out.println(i + "行" + j + " 列 is Blank type");
                        value = "";
                        break;
                    default:
                        System.out.println(i + "行" + j + " 列 is default type");
                        value = cell.toString();
                }
                if (value == null || "".equals(value)) {
                    continue;
                }
                linked.add(value);
            }
            list.add(linked);
        }
        return list;
    }
    /**
     * 读取Office 2007 excel
     * */
    private static List<List<Object>> read2007Excel(File file)
            throws IOException {
        List<List<Object>> list = new LinkedList<List<Object>>();
        // 构造 XSSFWorkbook 对象，strPath 传入文件路径
        XSSFWorkbook xwb = new XSSFWorkbook(new FileInputStream(file));
        // 读取第一章表格内容
        XSSFSheet sheet = xwb.getSheetAt(0);
        Object value = null;
        XSSFRow row = null;
        XSSFCell cell = null;
        int counter = 0;
        for (int i = sheet.getFirstRowNum(); counter < sheet
                .getPhysicalNumberOfRows(); i++) {
            row = sheet.getRow(i);
            if (row == null) {
                continue;
            } else {
                counter++;
            }
            List<Object> linked = new LinkedList<Object>();
            for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
                cell = row.getCell(j);
                if (cell == null) {
                    continue;
                }
                DecimalFormat df = new DecimalFormat("0");// 格式化 number String 字符
                SimpleDateFormat sdf = new SimpleDateFormat(
                        "yyyy-MM-dd HH:mm:ss");// 格式化日期字符串
                DecimalFormat nf = new DecimalFormat("#");// 格式化数字
                switch (cell.getCellType()) {
                    case XSSFCell.CELL_TYPE_STRING:
                        System.out.println(i + "行" + j + " 列 is String type");
                        value = cell.getStringCellValue();
                        break;
                    case XSSFCell.CELL_TYPE_NUMERIC:
                      System.out.println(i + "行" + j
                                + " 列 is Number type ; DateFormt:"
                                + cell.getCellStyle().getDataFormatString());
                        if ("@".equals(cell.getCellStyle().getDataFormatString())) {
                            value = df.format(cell.getNumericCellValue());
                        } else if ("General".equals(cell.getCellStyle()
                                .getDataFormatString())) {
                            value = nf.format(cell.getNumericCellValue());
                        } else {
                            value = sdf.format(HSSFDateUtil.getJavaDate(cell
                                    .getNumericCellValue()));
                        }
                        break;
                    case XSSFCell.CELL_TYPE_BOOLEAN:
                        System.out.println(i + "行" + j + " 列 is Boolean type");
                        value = cell.getBooleanCellValue();
                        break;
                    case XSSFCell.CELL_TYPE_BLANK:
                        System.out.println(i + "行" + j + " 列 is Blank type");
                        value = "";
                        break;
                    default:
                        System.out.println(i + "行" + j + " 列 is default type");
                        value = cell.toString();
                }
                if (value == null || "".equals(value)) {
                    continue;
                }
                linked.add(value);
            }
            list.add(linked);
        }
        return list;
    }

    public  static  <T> List<T> convert(List<List<Object>> list , Map<String,String> config,Class T){
        Map<Integer,String> index = new HashMap<Integer,String>();
        List title = list.get(0);
        for(int i=0;i<title.size();i++){
            index.put(i,config.get(String.valueOf(title.get(i))));
        }
        JSONArray result = new JSONArray();
        for(int i=1;i<list.size();i++){
            List bean = list.get(i);
            JSONObject jo = new JSONObject();
            for(int j=0;j<bean.size();j++){
            	String value = String.valueOf(bean.get(j));
            	if(bean.get(j)==null){
            		value = null;
            	}
                jo.put(index.get(j), value);
            }
            result.add(jo);
        }
        return JSONObject.parseArray(result.toJSONString(),T);
    }
    /**
     * 对外提供读取excel 的方法
     * */
    public static List<List<Object>> readExcel(File file,int maxCell) throws IOException {
        String fileName = file.getName();
        String extension = fileName.lastIndexOf(".") == -1 ? "" : fileName
                .substring(fileName.lastIndexOf(".") + 1);
        if ("xls".equals(extension)) {
            return read2003Excel(file,maxCell);
        } else if ("xlsx".equals(extension)) {
            return read2007Excel(file,maxCell);
        } else {
            throw new IOException("不支持的文件类型");
        }
    }
    /**
     * 读取 office 2003 excel
     * @throws IOException
     * @throws FileNotFoundException
     */
    private static List<List<Object>> read2003Excel(File file,int maxCell)
            throws IOException {
        List<List<Object>> list = new LinkedList<List<Object>>();
        HSSFWorkbook hwb = new HSSFWorkbook(new FileInputStream(file));
        HSSFSheet sheet = hwb.getSheetAt(0);
        Object value = null;
        HSSFRow row = null;
        HSSFCell cell = null;
        int counter = 0;
        for (int i = sheet.getFirstRowNum(); counter < sheet
                .getPhysicalNumberOfRows(); i++) {
            row = sheet.getRow(i);
            if (row == null) {
                continue;
            } else {
                counter++;
            }
            List<Object> linked = new LinkedList<Object>();
            for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
            	if(j>=maxCell){
            		break;
            	}
                cell = row.getCell(j);
                if (cell == null) {
                	value=null;
                	linked.add(value);
                    continue;
                }
                DecimalFormat df = new DecimalFormat("#");// 格式化 number String 字符
                SimpleDateFormat sdf = new SimpleDateFormat(
                        "yyyy-MM-dd HH:mm:ss");// 格式化日期字符串
                DecimalFormat nf = new DecimalFormat("#");// 格式化数字
                switch (cell.getCellType()) {
                    case XSSFCell.CELL_TYPE_STRING:
                        System.out.println(i + "行" + j + " 列 is String type");
                        value = cell.getStringCellValue();
                        break;
                    case XSSFCell.CELL_TYPE_NUMERIC:
                        System.out.println(i + "行" + j
                                + " 列 is Number type ; DateFormt:"
                                + cell.getCellStyle().getDataFormatString());
                        if ("@".equals(cell.getCellStyle().getDataFormatString())) {
                            value = df.format(cell.getNumericCellValue());
                        } else if ("General".equals(cell.getCellStyle()
                                .getDataFormatString())) {
                            value = nf.format(cell.getNumericCellValue());
                        } else {
                            value = sdf.format(HSSFDateUtil.getJavaDate(cell
                                    .getNumericCellValue()));
                        }
                        break;
                    case XSSFCell.CELL_TYPE_BOOLEAN:
                        System.out.println(i + "行" + j + " 列 is Boolean type");
                        value = cell.getBooleanCellValue();
                        break;
                    case XSSFCell.CELL_TYPE_BLANK:
                        System.out.println(i + "行" + j + " 列 is Blank type");
                        value = "";
                        break;
                    default:
                        System.out.println(i + "行" + j + " 列 is default type");
                        value = cell.toString();
                }
                if (value == null || "".equals(value)) {
                	value=null;
                	linked.add(value);
                    continue;
                }
                linked.add(value);
            }
            list.add(linked);
        }
        return list;
    }
    /**
     * 读取Office 2007 excel
     * */
    private static List<List<Object>> read2007Excel(File file,int maxCell)
            throws IOException {
        List<List<Object>> list = new LinkedList<List<Object>>();
        // 构造 XSSFWorkbook 对象，strPath 传入文件路径
        XSSFWorkbook xwb = new XSSFWorkbook(new FileInputStream(file));
        // 读取第一章表格内容
        XSSFSheet sheet = xwb.getSheetAt(0);
        Object value = null;
        XSSFRow row = null;
        XSSFCell cell = null;
        int counter = 0;
        for (int i = sheet.getFirstRowNum(); counter < sheet
                .getPhysicalNumberOfRows(); i++) {
            row = sheet.getRow(i);
            if (row == null) {
                continue;
            } else {
                counter++;
            }
            List<Object> linked = new LinkedList<Object>();
            for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
                cell = row.getCell(j);
                if (cell == null) {
                    continue;
                }
                DecimalFormat df = new DecimalFormat("0");// 格式化 number String 字符
                SimpleDateFormat sdf = new SimpleDateFormat(
                        "yyyy-MM-dd HH:mm:ss");// 格式化日期字符串
                DecimalFormat nf = new DecimalFormat("#");// 格式化数字
                switch (cell.getCellType()) {
                    case XSSFCell.CELL_TYPE_STRING:
                        System.out.println(i + "行" + j + " 列 is String type");
                        value = cell.getStringCellValue();
                        break;
                    case XSSFCell.CELL_TYPE_NUMERIC:
                      System.out.println(i + "行" + j
                                + " 列 is Number type ; DateFormt:"
                                + cell.getCellStyle().getDataFormatString());
                        if ("@".equals(cell.getCellStyle().getDataFormatString())) {
                            value = df.format(cell.getNumericCellValue());
                        } else if ("General".equals(cell.getCellStyle()
                                .getDataFormatString())) {
                            value = nf.format(cell.getNumericCellValue());
                        } else {
                            value = sdf.format(HSSFDateUtil.getJavaDate(cell
                                    .getNumericCellValue()));
                        }
                        break;
                    case XSSFCell.CELL_TYPE_BOOLEAN:
                        System.out.println(i + "行" + j + " 列 is Boolean type");
                        value = cell.getBooleanCellValue();
                        break;
                    case XSSFCell.CELL_TYPE_BLANK:
                        System.out.println(i + "行" + j + " 列 is Blank type");
                        value = "";
                        break;
                    default:
                        System.out.println(i + "行" + j + " 列 is default type");
                        value = cell.toString();
                }
                if (value == null || "".equals(value)) {
                    continue;
                }
                linked.add(value);
            }
            list.add(linked);
        }
        return list;
    }
	public static void main(String[] args) {
		List<String> row = new ArrayList<String>();
		List<List> data = new ArrayList<List>(); 
		row.add("A");
		row.add("B");
		row.add("C");
		data.add(row);
		String[] titles = new String[]{"1","2","3"};
		HSSFWorkbook book = toWorkBook("test", titles, data);
		try {
			FileOutputStream out =new FileOutputStream(new File("F://test.xls"));
			book.write(out);
			out.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}

